#!/usr/bin/python  
# -*- coding:utf-8 -*-
from calculate.utils import distance
import math
import random

Alpha = 1
Beta = 3
DEFAULT_PHEROMONES = 0
Q = 1  # 信息素强度
P = 0.9  # 稀释系数
MAX_LOAD = 8000  # 最大载重量 kg

# 公式系数
def func(pheromone, yita):
    rate = pheromone ** Alpha * yita ** Beta
    return rate


def yita(distance):  # 启发式函数
    yita = 1 / distance
    return yita


def choicerate(ants, map):
    sum = 0
    rate = []
    for place in list((set(ants.quest.startplace) | set(ants.quest.endplace)) - set(ants.tabu)):
        sum += func(map.phromone(ants.place, place), yita(map.distance(ants.place, place)))
    if sum < math.e ** -20 :
        rate = random.choice(list((set(ants.quest.startplace) | set(ants.quest.endplace)) - set(ants.tabu)))
    else:
        for place in list((set(ants.quest.startplace) | set(ants.quest.endplace)) - set(ants.tabu)):
            rate += [func(map.phromone(ants.place, place), yita(map.distance(ants.place, place))) / sum]
    return rate


def random_pick(some_list, probabilities):
    if isinstance(probabilities,str):
        item = probabilities
    else:
        x = random.uniform(0, 1)
        cumulative_probability = 0.0
        for item, item_probability in zip(some_list, probabilities):
            cumulative_probability += item_probability#有很低概率出问题
            if x < cumulative_probability:
                return item
    return None


class Place:
    def __init__(self, longitude, dimension, isPark=False):
        self.longitude = longitude
        self.dimension = dimension
        self.isPark = isPark

    def __eq__(self, other):
        if self.longitude == other.longitude and self.dimension == other.dimension:
            return True
        else:
            return False


class Line:
    def __init__(self, first=None, second=None):
        self.places = []
        self.places.append(first)
        self.places.append(second)
        self.distance = self.get_distance()
        self.pheromones = DEFAULT_PHEROMONES

    def __eq__(self, other):
        if self.places[0] == other.places[0] and self.places[1] == other.places[1]:
            return True
        elif self.places[0] == other.places[1] and self.places[1] == other.places[0]:
            return True
        else:
            return False

    def get_distance(self):
        return distance(self.places[0].longitude, self.places[0].dimension, self.places[1].longitude,
                        self.places[1].dimension)

    def release_pheromones(self, distance):
        self.pheromones = Q / distance


class Map:
    def __init__(self):
        self.lines = []
        self.places = []

    def getLine(self, first_place, second_place):
        for i in range(len(self.lines)):
            if first_place in self.lines[i].places and second_place in self.lines[i].places:
                return self.lines[i]
        return None

    """def add_waybill_place(self,waybill):
        first_place = Place(waybill.startLongitude, waybill.startDimension)
        second_place = Place(waybill.endLongitude, waybill.endDimension)
        self.add_place(first_place)
        self.add_place(second_place)"""

    def add_line(self, n_line):
        is_merge = False
        for line in self.lines:
            if line == n_line:
                is_merge = True
                break
        if not is_merge:
            self.lines.append(n_line)
            pass

    def add_place(self, n_place):
        is_merge = False
        for place in self.places:
            if place == n_place:
                is_merge = True
                break
        if not is_merge:
            self.places.append(n_place)

    def join_all_place(self):
        for i in range(0, len(self.places)):
            for j in range(0, len(self.places)):
                if i != j:
                    line = Line(first=self.places[i], second=self.places[j])
                    self.add_line(line)

    def volatilize_pheromones(self):
        for lines in self.lines:
            lines.pheromones = lines.pheromones * (1 - P)


class Schedule:
    def __init__(self):
        self.lines = []
        self.accept_waybills = []
        self.completed_waybills = []
        self.sum_koli = 0.0

    """def __sum_koli(self):
        k = 0.0
        for line in self.lines:
            k += line.get_distance()
        return k"""

    """def add_line(self, line):
        all_koli = line.distance + self.sum_koli
        if all_koli >= MAX_KILO:
            return False
        else:
            self.lines.append(line)
            self.sum_koli += line.distance"""

    def is_completed(self):
        return not self.accept_waybills


class Ants:
    def __init__(self, max_weight, park_place):
        self.max_weight = max_weight
        self.schedule = None
        self.completed_schedules = []
        self.cur_place = park_place

    def upload(self):
        for quest in self.quest:
            if self.place in quest.startplace and self.load + quest.task < self.volume:
                self.load += quest.task
                self.updatetabu(self.place)

    def download(self):
        for quest in self.quest:
            if self.place in quest.endplace and self.load > quest.task:
                self.load -= quest.task
                quest.complete()
                self.updatetabu(self.place)

    def move(self, targetplace):
        self.place = targetplace
        self.route += targetplace

    def updatetabu(self, place):
        self.tabu += place

    def release_pheromones(self, route):
        for i in route:
            i
        self.pheromones = Q / route

    def iscomplete(self):
        for quest in self.quest:
            if quest.state is False: return False
        return True
